package com.aaa.security;

import com.aaa.Filter.OauthClientCredentialsTokenEndpointFilter;
import com.aaa.exception.OAuthAuthenticationEntryPoint;
import com.aaa.exception.OauthResponseExceptionTranslator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.List;

@Configuration
@EnableAuthorizationServer
public class OauthConfig extends AuthorizationServerConfigurerAdapter {
    private final String SIGNING_KEY = "book";
    @Resource
    PasswordEncoder passwordEncoder;
    @Resource
    AuthenticationManager authenticationManager;
    @Resource
    DataSource dataSource;
    @Resource
    UserDetailsConfig userDetailsConfig;
    @Resource
    JwtEnhancer jwtEnhancer;

    /**
     * jwttoken装换器
     * @return
     */
    @Bean
    public JwtAccessTokenConverter jwtTokenConverter(){
        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
        jwtAccessTokenConverter.setSigningKey(SIGNING_KEY);
        jwtAccessTokenConverter.setVerifierKey(SIGNING_KEY);
        return jwtAccessTokenConverter;
    }
    /**
     * 保存在 内存中/redis
     * 生成方式 jwt
     */
    @Bean
   public TokenStore jwtTokenStore(){
        //保存方式
        // new InMemoryTokenStore(); 保存在内存中
        // new RedisTokenStore(); 保存在redis
     return new JwtTokenStore(jwtTokenConverter());
    }
    @Bean
    public WebResponseExceptionTranslator initResponseExceptionTranslator(){
    return new OauthResponseExceptionTranslator();
    }
    /**
     * 密码认证管理器
     *
     * @param endpoints
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints){
        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        List<TokenEnhancer> list = new ArrayList<>();
        list.add(jwtEnhancer);
        list.add(jwtTokenConverter());
        tokenEnhancerChain.setTokenEnhancers(list);

        // token
        endpoints
                // jwt生成
                .accessTokenConverter(jwtTokenConverter())
                // 增强
                .tokenEnhancer(tokenEnhancerChain)
                // 存储方式
                .tokenStore(jwtTokenStore())
                // 更新刷新token
                .reuseRefreshTokens(false)
                .userDetailsService(userDetailsConfig)
                .authenticationManager(authenticationManager)
                //异常翻译器，解析异常(授权类型错误,用户名密码错误)
                .exceptionTranslator(initResponseExceptionTranslator());

    }

    /**
     * 客户端详情配置
     * */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
          //从数据库中加载信息
            clients.jdbc(dataSource).passwordEncoder(passwordEncoder);
    }
   @Resource
  OAuthAuthenticationEntryPoint oAuthAuthenticationEntryPoint;

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.passwordEncoder(passwordEncoder);
        //允许表单进行客户端验证
        //security.allowFormAuthenticationForClients();
        //oauth2中 获取token,验证token接口不需要认证
        security.tokenKeyAccess("permitAll");
        security.checkTokenAccess("permitAll");

        AuthorizationServerSecurityConfigurer authorizationServerSecurityConfigurer = security.authenticationEntryPoint(oAuthAuthenticationEntryPoint);
        OauthClientCredentialsTokenEndpointFilter oauthClientCredentialsTokenEndpointFilter = new OauthClientCredentialsTokenEndpointFilter(oAuthAuthenticationEntryPoint,authorizationServerSecurityConfigurer);
        oauthClientCredentialsTokenEndpointFilter.afterPropertiesSet();
        security.authenticationEntryPoint(oAuthAuthenticationEntryPoint)
                .addTokenEndpointAuthenticationFilter(oauthClientCredentialsTokenEndpointFilter);
//        AuthorizationServerSecurityConfigurer authorizationServerSecurityConfigurer = security.authenticationEntryPoint(oAuthAuthenticationEntryPoint);
//        OauthClientCredentialsTokenEndpointFilter oauthClientCredentialsTokenEndpointFilter = new OauthClientCredentialsTokenEndpointFilter(oAuthAuthenticationEntryPoint);
//
//        oauthClientCredentialsTokenEndpointFilter.afterPropertiesSet();
//
        //自定义处理器,用于处理客户端id，密码的异常
    }


}
